package services

import (
	"alarm_protocol/mqtt"
	protocol "alarm_protocol/services/alarm_protocol"
	"errors"
	"fmt"
	"net"
	"sync"

	"github.com/sirupsen/logrus"
)

type TCPObject struct {
	Mutex     *sync.Mutex //互斥锁
	Conn      net.Conn    //连接
	DeviceID  string      //设备在平台的唯一标识
	UID       string      //硬件设备唯一标识
	ReplyFlag bool        //是否需要回复
}

// 当设备与平台连接的时候，开启一个goroutine接管连接
func NewTCPObject(conn net.Conn) {
	defer conn.Close()
	w := &TCPObject{
		Conn:  conn,
		Mutex: &sync.Mutex{},
	}
	w.Start()
}

func (w *TCPObject) Start() {
	defer w.Conn.Close() // 确保连接最终被关闭

	// make a buffer to hold incoming data
	buf := make([]byte, 1024)
	for {
		// read the incoming connection into the buffer
		reqLen, err := w.Conn.Read(buf)
		if err != nil {
			logrus.Errorf("Error reading: %v", err)
			break // 如果出错(比如连接关闭),退出循环
		}
		logrus.Infof("Received data: %s", string(buf[:reqLen]))
		if reqLen == 0 {
			continue // 如果没有读到数据,继续下一次循环
		}
		// 鉴权
		if w.auth(buf[:reqLen]) != nil {
			break
		}
		// 处理数据
		w.processData(buf[:reqLen])
	}

	logrus.Info("Connection closed")
}

func (w *TCPObject) processData(data []byte) {
	// TODO: 在这里添加数据处理逻辑
	// 例如: 解析协议,执行相应的操作等
	pkg, err := protocol.Deserialize(data)
	if err != nil {
		logrus.Errorf("Error deserializing: %v", err)
		return
	}
	logrus.Infof("Received data: %v", pkg)
	w.HandleCommand(pkg)
}

// 鉴权
func (w *TCPObject) auth(buf []byte) error {
	// 鉴权
	if w.UID == "" {
		reqLen := len(buf)
		// 解析并打印源地址（假定源地址占6字节，从第13字节开始）
		if reqLen > 18 { // 确保缓冲区有足够的数据来读取源地址
			// 解析源地址并转为字符串
			w.UID = fmt.Sprintf("%x", buf[12:18])
			logrus.Warn("SourceAddress[UID][凭证]: ", w.UID)
			device, err := AuthDevice(w.UID)
			if err != nil {
				logrus.Errorf("Error getting device config: %v", err)
				return err
			}
			logrus.Warn("认证通过: ", device)
			w.DeviceID = device.Data.ID
		} else {
			logrus.Warn("Received data is too short to extract source address")
			return errors.New("received data is too short to extract source address")
		}

		return nil
	}
	return nil
}

func (w *TCPObject) HandleCommand(pkg *protocol.Packet) {
	switch pkg.Command {
	case 0x01: // 控制命令
		w.handleControlCommand(pkg)
	case 0x02: // 发送数据
		w.handleSendData(pkg)
	case 0x05: // 应答
		w.handleResponse(pkg)
	default:
		logrus.Warnf("Unknown command: %02x", pkg.Command)
	}
}

func (w *TCPObject) handleControlCommand(pkg *protocol.Packet) {
	logrus.Info("Handling control command")
	logrus.Infof("Received control command: %v", pkg)
	// 实现控制命令的逻辑
	// 例如: 时间同步等
}

// 处理发送数据
func (w *TCPObject) handleSendData(pkg *protocol.Packet) {
	logrus.Info("Handling send data[发送数据] command")

	if len(pkg.Data) < 2 {
		logrus.Error("Invalid data length for send data command")
		return
	}

	typeFlag := pkg.Data[0]
	objectCount := pkg.Data[1]

	logrus.Infof("Type flag[类型标志]: %d, Object count[信息对象数目]: %d", typeFlag, objectCount)

	switch typeFlag {
	case 0x03: // 上传仪表模拟量值
		data, error := protocol.HandleAnalogValues(pkg.Data[2:], int(objectCount))
		if error != nil {
			logrus.Errorf("Error handling analog values: %v", error)
			// 否TODO认回答
			return
		}
		logrus.Infof("Analog values: %v", data)
		err := mqtt.PublishTelemetry(w.DeviceID, data)
		if err != nil {
			logrus.Errorf("Error publishing telemetry: %v", err)
		}

	default:
		logrus.Warnf("Unknown type flag: %d", typeFlag)
	}

	// 发送确认回答
	rsp, err := pkg.Respond(w.DeviceID)
	if err != nil {
		logrus.Errorf("Error responding: %v", err)
		return
	}
	logrus.Debug("==>device response[确认回答]: ", rsp)
	w.Conn.Write(rsp)
}

func (w *TCPObject) handleResponse(pkg *protocol.Packet) {
	logrus.Info("Handling response")
	logrus.Infof("Received response: %v", pkg)
	// 实现应答的逻辑
	// 例如: 处理返回的查询信息
}

// func (w *TCPObject) handleDeviceStatus(data []byte) {
// 	logrus.Info("Handling device status")
// 	logrus.Infof("Device status: %v", data)
// 	// 实现处理设备状态的逻辑
// }

// func (w *TCPObject) handleAnalogValue(data []byte) {
// 	logrus.Info("Handling analog value")
// 	logrus.Infof("Analog value: %v", data)
// 	// 实现处理模拟量值的逻辑
// }

// func (w *TCPObject) handleDeviceConfig(data []byte) {
// 	logrus.Info("Handling device configuration")
// 	logrus.Infof("Device configuration: %v", data)
// 	// 实现处理设备配置的逻辑
// }
